/*
 * Copyright (C) 2021 NaviTech
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @ingroup     core_internal
 * @{
 *
  * @file         sfc_mem_ringbuf.h
  * @brief
  * @note         在cortexm3和cortexm4中，bool，uint8，uint16，uint32 读写是原子操作（无论是否4字节对齐），也就说不用加锁。
  * @author       lixinliang
  * @date         2021-08-14
  *
  * @par          修改日志
  * <table>
  * <tr><th>Date        <th>Version          <th>Author                        <th>Description
  * <tr><td>2021-08-14  <td>1.0              <td>xinliang6176@126.com          <td>创建初始版本
  * @copyright
  */

#include "sfc_mem_ringbuf.h"

int32_t TSFCMemRingbufCreate(TSFCMemRingbuf *self, uint8_t *buff, int32_t buff_size)
{
    int32_t result = kSFCErrInvaildArg;

    if (buff != NULL && buff_size > 0)
    {
        self->buff_begin_ = buff;
        self->buff_end_ = buff + buff_size;

        self->wr_pos_ = self->buff_begin_;
        self->rd_pos_ = self->buff_begin_;

        self->wr_size_ = 0;
        self->rd_size_ = 0;

        result = kSFCErrOk;
    }

    return result;
}

void TSFCMemRingbufDestroy(TSFCMemRingbuf *self)
{
    memset(self, 0x00, sizeof(*self));
}

void TSFCMemRingbufReset(TSFCMemRingbuf *self)
{
    self->wr_pos_ = self->buff_begin_;
    self->rd_pos_ = self->buff_begin_;

    self->wr_size_ = 0;
    self->rd_size_ = 0;
}

int32_t TSFCMemRingbufPush(TSFCMemRingbuf *self, const void *data, int32_t data_size)
{
    int32_t result = 0;
    int32_t space = TSFCMemRingbufCapacity(self) - TSFCMemRingbufBytes(self);

    if (data != NULL && data_size > 0 && space > 0)
    {
        int32_t size_to_end = self->buff_end_ - self->wr_pos_;

        // 校准实际可以写入的字节数
        data_size = data_size > space ? space : data_size;
        result = data_size;

        if (size_to_end > data_size) size_to_end = data_size;

        memmove(self->wr_pos_, data, size_to_end);

        self->wr_pos_ += size_to_end;
        if (self->wr_pos_ >= self->buff_end_)
            self->wr_pos_ = self->buff_begin_;

        // 写到末尾，剩余字节数
        data_size -= size_to_end;
        if (data_size > 0)
        {
            memmove(self->wr_pos_, (char *)data + size_to_end, data_size);
            self->wr_pos_ += data_size;
        }

        self->wr_size_ += result;
    }

    return result;
}

int32_t TSFCMemRingbufPop(TSFCMemRingbuf *self, void *buff, int32_t buff_size)
{
    int32_t result = 0;
    uint32_t buffed_bytes = TSFCMemRingbufBytes(self); // 不要担心溢出，

    if (buff != NULL && buff_size > 0 && buffed_bytes > 0)
    {
        int32_t size_to_end = self->buff_end_ - self->rd_pos_;

        // 校准实际可读取的字计数
        if (buff_size > buffed_bytes)
            buff_size = buffed_bytes;

        result = buff_size;

        if (size_to_end > buff_size)
            size_to_end = buff_size;

        memmove(buff, self->rd_pos_, size_to_end);

        self->rd_pos_ += size_to_end;
        if (self->rd_pos_ >= self->buff_end_)
            self->rd_pos_ = self->buff_begin_;

        // 读到末尾，剩余字节数
        buff_size -= size_to_end;
        if (buff_size > 0)
        {
            memmove((char *)buff + size_to_end, self->rd_pos_, buff_size);
            self->rd_pos_ += buff_size;
        }

        self->rd_size_ += result;
    }

    return result;
}

int32_t TSFCMemRingbufDrop(TSFCMemRingbuf *self, int32_t buff_size)
{
    int32_t result = 0;
    uint32_t buffed_bytes = TSFCMemRingbufBytes(self); // 不要担心溢出，

    if (buff_size > 0 && buffed_bytes > 0)
    {
        int32_t size_to_end = self->buff_end_ - self->rd_pos_;

        // 校准实际可读取的字计数
        if (buff_size > buffed_bytes)
            buff_size = buffed_bytes;

        result = buff_size;

        if (size_to_end > buff_size)
            size_to_end = buff_size;

        // memmove(buff, self->rd_pos_, size_to_end);

        self->rd_pos_ += size_to_end;
        if (self->rd_pos_ >= self->buff_end_)
            self->rd_pos_ = self->buff_begin_;

        // 读到末尾，剩余字节数
        buff_size -= size_to_end;
        if (buff_size > 0)
        {
            // memmove((char *)buff + size_to_end, self->rd_pos_, buff_size);
            self->rd_pos_ += buff_size;
        }

        self->rd_size_ += result;
    }

    return result;
}

int32_t TSFCMemRingbufPeek(TSFCMemRingbuf *self, void *buff, int32_t buff_size)
{
    int32_t result = 0;
    uint32_t buffed_bytes = TSFCMemRingbufBytes(self); // 不要担心溢出，

    if (buff != NULL && buff_size > 0 && buffed_bytes > 0)
    {
        int32_t size_to_end = self->buff_end_ - self->rd_pos_;

        // 校准实际可读取的字计数
        if (buff_size > buffed_bytes)
            buff_size = buffed_bytes;

        result = buff_size;

        if (size_to_end > buff_size)
            size_to_end = buff_size;

        memmove(buff, (const void *)self->rd_pos_, size_to_end);

        // 读到末尾，剩余字节数
        buff_size -= size_to_end;
        if (buff_size > 0)
        {
            memmove((char *)buff + size_to_end, self->buff_begin_, buff_size);
        }
    }

    return result;
}
